﻿#region Copyright information
// 
// Copyright © 2012-2013 Yongkee Cho. All rights reserved.
// 
// This code is a part of the SubnetworkToolkit and governed under the terms of the
// GNU Lesser General  Public License (LGPL) version 2.1 which accompanies this distribution.
// For more information on the LGPL, please visit http://bol.codeplex.com/license.
// 
// - Filename: Program.cs
// - Author: Yongkee Cho
// - Email: yongkeecho@outlook.com
// - Date Created: 2013-01-30 2:55 PM
// - Last Modified: 2013-01-30 3:21 PM
// 
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using CommandLine;
using BOL.Maths.Functions;
using SubnetworkToolkit.IO;

namespace SubnetworkToolkit.EnrichmentTest
{
    static class Program
    {
        static void Main(string[] args)
        {
            var options = new Options();

            try
            {
                // parse arguments
                var parser = new CommandLineParser(new CommandLineParserSettings(Console.Error));
                parser.ParseArguments(args, options);

                if (args.Length == 0 || args[0] == "-h")
                    Console.Error.Write(options.GetUsage());
                else
                {
                    var sourceFile = options.SourceFile;
                    var targetFile = options.TargetFile;

                    // Read source gmt file
                    var sourceGmt = new GmtReader(sourceFile);
                    var intputGeneSets = sourceGmt.Read();
                    sourceGmt.Close();

                    // Read target gmt file
                    var targetGmt = new GmtReader(targetFile);
                    var targetGeneSets = targetGmt.Read();
                    targetGmt.Close();

                    // Read p-value cutoff
                    var pValueCutoff = options.PValueCutoff;

                    // 
                    var sigGeneSets = new Dictionary<GeneSet, List<Tuple<GeneSet, double>>>();

                    foreach (var sourceGeneSet in intputGeneSets)
                    {
                        var sourceGenes = sourceGeneSet.Genes.Select(x => x.Id).ToList();
                        var m = sourceGenes.Count;

                        foreach (var targetGeneSet in targetGeneSets)
                        {
                            var targetGenes = targetGeneSet.Genes.Select(x => x.Id).ToList();
                            var n = targetGenes.Count;
                            var k = sourceGenes.Intersect(targetGenes).Count();
                            if (k > 0)
                            {
                                var p = Enumerable.Range(1, k).Sum(i => CountingFunctions.Hypergeometric(20069, m, n, i));
                                if (p <= pValueCutoff)
                                {
                                    //var name = targetGeneSet.Name;
                                    if (sigGeneSets.ContainsKey(targetGeneSet))
                                        sigGeneSets[targetGeneSet].Add(new Tuple<GeneSet, double>(sourceGeneSet, p));
                                    else
                                    {
                                        sigGeneSets.Add(targetGeneSet, new List<Tuple<GeneSet, double>>());
                                        sigGeneSets[targetGeneSet].Add(new Tuple<GeneSet, double>(sourceGeneSet, p));
                                    }
                                }
                            }
                        }
                    }

                    foreach (var sigGeneSet in sigGeneSets.OrderBy(x => x.Value.Min(y => y.Item2)))
                    {
                        var sigTargetGeneSet = sigGeneSet.Key;
                        var sw = new StreamWriter(String.Format("{0}.csv", sigTargetGeneSet.Name));

                        //Console.WriteLine("{0}\t{1}\t{2}", sigGeneSet.Key.Name, sigGeneSet.Key.Description, sigGeneSet.Value.Min(x => x.Item2));
                        foreach (var gene in sigTargetGeneSet.Genes)
                        {
                            sw.WriteLine("{0},1", gene.Id);
                        }

                        sw.Close();
                    }
                }
            }
            catch (Exception e)
            {
                Console.Error.Write(e.Message);
            }
        }
    }
}
